package com.zjl.SpringBoot.第03章_Web开发.E_内容协商;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;

@Configuration
public class MyYamlHttpMessageConverter extends AbstractHttpMessageConverter<Object> {

    ObjectMapper objectMapper;

    public MyYamlHttpMessageConverter() {

        super(new MediaType("text","yaml", StandardCharsets.UTF_8));//告诉spring boot 支持哪种媒体类型
        YAMLFactory yamlFactory = new YAMLFactory();
        yamlFactory.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);//禁用文档开始标记： ---
        this.objectMapper = new ObjectMapper(yamlFactory);
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        //只支持对象类型,不是基本类型
        return true;
    }

    @Override //入参   配合 @RequestBody
    protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return null;
    }

    //配置一个可以将 数据 改为 yaml的 HttpMessageConverter

    @Override //出参   配合 @ResponseBody
    protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

        try(OutputStream body = outputMessage.getBody();) {
            this.objectMapper.writeValue(body,o);//有些类型不支持  如   LocalDateTime
        }

    }

}
/**
 * 自定义Message Converter
 *  自定义后，能产出的类型会添加进去
 * 可以自己配置  详见 com.example.springboot.config.LongMessageConverters
 *
 * 也可以将自定义类型  添加在基于参数的内容协商
 *  详见 com.example.springboot.config.MyWebMvcConfigurer.configureContentNegotiation()
 *    这个是重写 所以会覆盖  原来的 xml 和 json  所以要再写一遍
 * 浏览器发请求直接返回xml              【application/xml】
 * 如果是ajax请求返回json              【application/json】
 * 如果自定义app发请求，返回自定义协议数据   【application/x-long】
 *
 */
@Configuration
class 自定义响应头 implements HttpMessageConverter<Person> {

    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return clazz.isAssignableFrom(Person.class);
    }//能不能读

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return clazz.isAssignableFrom(Person.class);
    }//能不能写


    /**
     * *服务器要统计所有 MessageConverter 都能写出哪些内容类型
     * application/x-long
     */
    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return MediaType.parseMediaTypes("application/x-long");
    }

    DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE_TIME;

    //写入写出  必须对应
    @Override
    public Person read(Class<? extends Person> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        String temp = StreamUtils.copyToString(inputMessage.getBody(), Charset.forName("UTF-8"));
        String[] tempArr = temp.split(";");
        return new Person(tempArr[0],
                "true".equals(tempArr[1]),
                LocalDateTime.from(DateTimeFormatter.ISO_LOCAL_DATE_TIME.parse(tempArr[2])),
                Integer.valueOf(tempArr[3]));
    }//自定义 写入

    @Override
    public void write(Person person, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        String data = //user.toString();
                person.getUserName() + ";" +
                        person.getBoss() + ";" +
                        person.getBirth().toString() + ";" +
                        person.getAge();

        try (OutputStream body = outputMessage.getBody();){
            body.write(data.getBytes(StandardCharsets.UTF_8));
        }
    }//自定义 写出
}
